package com.multi.source.util;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.multi.common.constant.SourceConstant;
import com.multi.source.domain.BkDataSourceInfo;
import com.multi.source.domain.BkSqlInfo;
import com.multi.source.mapper.SystemDbMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: pzj
 * @Date: 2024/11/23 10:33
 * @Description: 数据库工具
 **/
@Slf4j
@Component
public class DataBaseUtils {


    @Autowired
    private DataSource dataSource;

    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;

    @Autowired
    private SystemDbMapper systemDbMapper;


    /**
     * 创建数据库连接
     *
     * @param bkDataSourceInfo
     * @return
     */
    public Boolean createConnect(BkDataSourceInfo bkDataSourceInfo, String... dbNames) {
        //创建一个临时连接，进行数据库的生成
        String dbIp = bkDataSourceInfo.getDbIp();
        String dbPort = bkDataSourceInfo.getDbPort();
        String dbName = bkDataSourceInfo.getDbName();
        String userName = bkDataSourceInfo.getUsername();
        String passWord = bkDataSourceInfo.getPassword();
        //选择连接数据库的名称
        if (dbNames.length != 0) {
            dbName = dbNames[0];
        }
        //默认使用Mysql8.0，并且连接mysql数据库表，通过这个连接创建新的数据库数据
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        // 数据源参数配置
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        //固定使用mysql8
        String dbClassType = "com.mysql.cj.jdbc.Driver";
        String dbUrl = String.format("jdbc:mysql://%s:%s/%s?characterEncoding=utf8&useSSL=false", dbIp, dbPort, dbName);
        //需要设置时区信息
        dbUrl = dbUrl.concat("&serverTimezone=GMT%2B8");
        //这里使用IP进行区分
        if (dbNames.length != 0) {
            dataSourceProperty.setPoolName(dbIp);
        } else {
            dataSourceProperty.setPoolName(bkDataSourceInfo.getTenantId().toString());
        }
        dataSourceProperty.setUsername(userName);
        dataSourceProperty.setPassword(passWord);
        dataSourceProperty.setUrl(dbUrl);
        dataSourceProperty.setDriverClassName(dbClassType);
        // 数据源全部懒加载,避免一次性声明过多连接
        dataSourceProperty.setLazy(true);
        // 生成数据源
        DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
        // 添加到动态数据源中
        if (dbNames.length != 0) {
            ds.addDataSource(dbIp, dataSource);
            log.info("当前加载的数据源:{},加载完成!", dbIp);
        } else {
            ds.addDataSource(bkDataSourceInfo.getTenantId().toString(), dataSource);
            log.info("当前加载的数据源:{},加载完成!", bkDataSourceInfo.getTenantId().toString());
        }

        return Boolean.TRUE;
    }


    /**
     * 通过唯一标识删除数据库连接
     *
     * @param onlySign
     * @return
     */
    public Boolean deleteConnect(String onlySign) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ds.removeDataSource(onlySign);
        log.info("删除数据库连接{}", onlySign);
        return Boolean.TRUE;
    }

    /**
     * 动态创建数据表
     *
     * @param bkDataSourceInfo
     * @return
     */
    public Boolean createDataTable(BkDataSourceInfo bkDataSourceInfo) {
        //创建数据库源连接信息，
        String tenantId = bkDataSourceInfo.getTenantId().toString();
        //根据租户类型查询所需要的数据库信息
        BkSqlInfo bkSqlInfo = systemDbMapper.selectSqlInfo(bkDataSourceInfo.getTenantType());
        //循环读取插入数据表信息
        String sqlInfo = bkSqlInfo.getSqlInfo();
        if (sqlInfo == null) {
            return Boolean.FALSE;
        }
        String[] split = sqlInfo.split(";");
        for (String info : split) {
            systemDbMapper.createDataTable(tenantId, info);
        }
        return Boolean.TRUE;
    }

}
